#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QMessageBox>
#include<QClipboard>
#include<cmath>
#include<QFile>
#include<QFileDialog>
#include<QTextStream>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    PI(0.0),Diff(0),Radius(0),Length(0),index(0),
    radiusLimmit(new QIntValidator),lengthLimmit(new QIntValidator),diffLimmit(new QIntValidator),
    model(new QStandardItemModel)
{
    ui->setupUi(this);
    // 设置标题
    this->setWindowTitle("Calculate Cubage Volume");
    // 限制窗口大小
    this->setFixedSize( this->width(),this->height());
    // 限制半径范围
    radiusLimmit->setRange(1,1000000);
    ui->radiusInput->setValidator(radiusLimmit);
    // 限制长度范围
    lengthLimmit->setRange(1,1000000);
    ui->lengthInput->setValidator(lengthLimmit);
    // 限制差值范围
    diffLimmit->setRange(1,1000000);
    ui->diffInput->setValidator(diffLimmit);

    // 设置列头
    ResetTable();
    // 设置tableview
    ui->tableView->setModel(model);
    ui->tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
    ui->tableView->setContextMenuPolicy(Qt::ActionsContextMenu);
    // 设置拷贝
    copyAct=new QAction("Copy",this);
    copyAct->setShortcut(tr("Ctrl+C"));
    connect(copyAct,SIGNAL(triggered()),this,SLOT(copyData()));
    ui->tableView->addAction(this->copyAct);
}
// copyData 将选中的内容复制到粘贴板上
void MainWindow::copyData()
{
    int maxCol=0; int maxRow=0; int minCol=0; int minRow=0;
    QMap<QString,QString> map;
    QModelIndexList indexes =ui->tableView->selectionModel()->selectedIndexes();
    if(indexes.count()==0){
        QMessageBox::information(this, QString("Warning"),QString("Select Nothing"));
        return;
    }
    QModelIndex index;
    int k=0;
    foreach(index,indexes)
    {
        int col=index.column();
        int row=index.row();
        if(k==0)
        {
            minCol=col;
            minRow=row;
        }
        if(col>maxCol)
            maxCol=col;
        if(row>maxRow)
            maxRow=row;
        QString text = index.model()->data(index, Qt::EditRole).toString();
        map[QString::number(row) + "," + QString::number(col)] = text;
        k++;
    }
    QString rs = "";
    for (int row = minRow; row <= maxRow; row++) {
        for (int col = minCol; col <= maxCol; col++) {
            if (col != minCol) rs += "\t";
            rs += map[QString::number(row) + "," + QString::number(col)];
        }
        rs += "\r\n";
    }
    QClipboard* board = QApplication::clipboard();
    board->setText(rs);
}

MainWindow::~MainWindow()
{
    delete ui;
    delete model;
    delete radiusLimmit;
    delete lengthLimmit;
    delete diffLimmit;
    delete copyAct;
}

void MainWindow::on_generator_clicked()
{
    if(!ValidateData())
        return;
    // 清空表格之前的数据
    ResetTable();
    // 填充表格
    for(int height=0;height<=2*Radius;height+=Diff){
        model->setItem(index,0,new QStandardItem(QString::number(height)));
        double result=Calculate(Radius,height)*Length;
        result/=1e6;// mm^3 => L
        model->setItem(index,1,new QStandardItem(QString::number(result,10,2)));
        index++;
    }
}

bool MainWindow::ValidateData()
{
    QString RadiusStr=ui->radiusInput->text();
    if(RadiusStr.isEmpty())
    {
        QMessageBox::information(this, QString("Warning"),QString("Radius doesn't input"));
        return false;
    }
    Radius=RadiusStr.toInt();
    QString LengthStr=ui->lengthInput->text();
    if(LengthStr.isEmpty())
    {
        QMessageBox::information(this, QString("Warning"),QString("Length doesn't input"));
        return false;
    }
    Length=LengthStr.toInt();
    QString DiffStr=ui->diffInput->text();
    if(DiffStr.isEmpty())
    {
        QMessageBox::information(this, QString("Warning"),QString("Diff doesn't input"));
        return false;
    }
    Diff=DiffStr.toInt();
    if(Diff>2*Radius){
        QMessageBox::information(this, QString("Warning"),QString("Diff is bigger than diameter"));
        return false;
    }
    if(Diff==0){
        QMessageBox::information(this, QString("Error"),QString("Diff is 0"));
        return false;
    }
    QString PIStr=ui->piInput->text();
    if(PIStr.isEmpty())
    {
        QMessageBox::information(this, QString("Warning"),QString("π donesn't input"));
        return false;
    }
    PI=PIStr.toDouble();
    return true;
}

long double MainWindow::Calculate(int R, int h)
{
    double area = 0.0;
    // h < R
    if (h < R) {
        area = acos((R - h) * 1.0 / R) * R * R;
        area -= sqrt(2.0 * R * h - 2.0 * h * h) * (R - h);
    }
    // h > R
    else if (h > R && h < 2 * R) {
        area = PI * R * R;
        area -= Calculate(R, 2 * R - h);
    }
    // h==R
    else if (h == R) {
        area = PI * R * R / 2.0;
    }
    else if (h == 2 * R) {
        area = PI * R * R;
    }
    return area;
}

void MainWindow::SaveFile()
{
    if(index>0)
    {
        QString fileName = QFileDialog::getSaveFileName (this,tr("SaveData"),"",tr("File (*.csv)"));
        if(!fileName.isEmpty ())
        {
            QFile file(fileName);
            if(!file.open (QIODevice::WriteOnly))
            {
                QMessageBox msgBox;
                msgBox.setText("Save File Failed");
                msgBox.exec();
            }
            else
            {
                QString qs;
                for(int i=0;i<index;i++)
                {
                    QString s = model->data(model->index(i,0)).toString()+","+model->data(model->index(i,1)).toString()+",";
                    qs.append(s+"\r\n");
                }
                QTextStream stream(&file);
                stream << qs;
                stream.flush ();
                file.close ();
            }
        }
    }else{
        QMessageBox::information(this, QString("Error"),QString("Data doesn't exit!"));
    }
}

void MainWindow::ResetTable()
{
    if(!model)
        return;
    index=0;
    model->clear();
    model->setColumnCount(2);
    model->setHeaderData(0,Qt::Horizontal,QString("Height(mm)"));
    model->setHeaderData(1,Qt::Horizontal,QString("Volume(L)"));
}

void MainWindow::on_output_clicked()
{
    SaveFile();
}

void MainWindow::on_clear_clicked()
{
    ResetTable();
}
